/**
 * Project : CTI-dev
 * Package : com.voipackjapan.cti.utils
 * File    : CaptchaUtil.java
 */
package com.spring.Util;

import com.jhlabs.image.PinchFilter;
import com.jhlabs.math.ImageFunction2D;
import com.octo.captcha.component.image.backgroundgenerator.BackgroundGenerator;
import com.octo.captcha.component.image.backgroundgenerator.UniColorBackgroundGenerator;
import com.octo.captcha.component.image.color.RandomListColorGenerator;
import com.octo.captcha.component.image.deformation.ImageDeformation;
import com.octo.captcha.component.image.deformation.ImageDeformationByBufferedImageOp;
import com.octo.captcha.component.image.fontgenerator.FontGenerator;
import com.octo.captcha.component.image.fontgenerator.RandomFontGenerator;
import com.octo.captcha.component.image.textpaster.GlyphsPaster;
import com.octo.captcha.component.image.textpaster.TextPaster;
import com.octo.captcha.component.image.textpaster.glyphsvisitor.*;
import com.octo.captcha.component.image.wordtoimage.DeformedComposedWordToImage;
import com.octo.captcha.component.image.wordtoimage.WordToImage;
import com.octo.captcha.component.word.wordgenerator.RandomWordGenerator;
import com.octo.captcha.component.word.wordgenerator.WordGenerator;
import com.octo.captcha.engine.image.ListImageCaptchaEngine;
import com.octo.captcha.image.ImageCaptcha;
import com.octo.captcha.image.gimpy.GimpyFactory;
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageEncoder;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;


/**
 * <code>CaptchaUtil</code>
 * description.<p>验证码生成
 * <p>
 * <blockquote><pre>
 * use for ...
 * </pre></blockquote>
 *
 * @author Zhou Yin (<a href="mailto:vambad@gmail.com">Contact Me</a>)
 * @version 1.0, 2009-12-11
 * @since 1.0
 */
@SuppressWarnings("restriction")
public class CaptchaUtil extends ListImageCaptchaEngine {

    private static final Log log = LogFactory.getLog(CaptchaUtil.class);

    private static final String NUMERIC_CHARS = "23456789";
    private static final String UPPER_ASCII_CHARS = "ABCDEFGHJKLMNPQRSTXYZ";

    private static final CaptchaUtil instance = new CaptchaUtil();

    private ImageCaptcha imageCaptcha = null;

    private CaptchaUtil() {
    }

    public synchronized static CaptchaUtil getInstance() {
        return instance;
    }

    @Override
    protected void buildInitialFactories() {
        WordGenerator dictionnaryWords = new RandomWordGenerator(
                NUMERIC_CHARS
                        + UPPER_ASCII_CHARS
                //	+ LOWER_ASCII_CHARS
        );

        TextPaster randomPaster = new GlyphsPaster(
                6,
                6,
                new RandomListColorGenerator(
                        new Color[]{
                                new Color(23, 170, 27),
                                new Color(220, 34, 11),
                                new Color(23, 67, 172)
                        }
                ),
                new GlyphsVisitors[]{
                        new TranslateGlyphsVerticalRandomVisitor(1),
                        new RotateGlyphsRandomVisitor(Math.PI / 32),
                        new OverlapGlyphsUsingShapeVisitor(3),
                        new TranslateAllToRandomPointVisitor()
                }
        );

        BackgroundGenerator back = new UniColorBackgroundGenerator(250, 70, new Color(255, 255, 255));

        FontGenerator shearedFont = new RandomFontGenerator(
                50,
                50,
                new Font[]{
                        new Font("nyala", Font.BOLD, 50),
                        new Font("Bell MT", Font.PLAIN, 50),
                        new Font("Credit valley", Font.BOLD, 50)
                },
                false
        );

        PinchFilter pinch = new PinchFilter();

        pinch.setAmount(-.5f);
        pinch.setRadius(70);
        pinch.setAngle((float) (Math.PI / 16));
        pinch.setCentreX(0.5f);
        pinch.setCentreY(-0.01f);
        pinch.setEdgeAction(ImageFunction2D.CLAMP);

        PinchFilter pinch2 = new PinchFilter();
        pinch2.setAmount(-.6f);
        pinch2.setRadius(70);
        pinch2.setAngle((float) (Math.PI / 16));
        pinch2.setCentreX(0.3f);
        pinch2.setCentreY(1.01f);
        pinch2.setEdgeAction(ImageFunction2D.CLAMP);

        PinchFilter pinch3 = new PinchFilter();
        pinch3.setAmount(-.6f);
        pinch3.setRadius(70);
        pinch3.setAngle((float) (Math.PI / 16));
        pinch3.setCentreX(0.8f);
        pinch3.setCentreY(-0.01f);
        pinch3.setEdgeAction(ImageFunction2D.CLAMP);

        List<ImageDeformation> textDef = new ArrayList<ImageDeformation>();
        textDef.add(new ImageDeformationByBufferedImageOp(pinch));
        textDef.add(new ImageDeformationByBufferedImageOp(pinch2));
        textDef.add(new ImageDeformationByBufferedImageOp(pinch3));

        WordToImage word2image;
        word2image = new DeformedComposedWordToImage(
                false,
                shearedFont,
                back,
                randomPaster,
                new ArrayList<ImageDeformation>(),
                new ArrayList<ImageDeformation>(),
                textDef
        );

        this.addFactory(new GimpyFactory(dictionnaryWords, word2image, false));
    }

    public void writeCaptchaImage(HttpServletRequest request, HttpServletResponse response) {

        this.imageCaptcha = this.getNextImageCaptcha();
        request.getSession().setAttribute(U.SESSION_CAPTCHA, this.imageCaptcha);
        BufferedImage image = (BufferedImage) this.imageCaptcha.getChallenge();

        OutputStream outputStream = null;
        try {
            outputStream = response.getOutputStream();

            response.setHeader("Cache-Control", "no-store");
            response.setHeader("Pragma", "no-cache");
            response.setDateHeader("Expires", 0);
            response.setContentType("image/jpeg");

            JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(outputStream);
            encoder.encode(image);

            outputStream.flush();
            outputStream.close();
            outputStream = null;
        } catch (IOException ex) {
            if (log.isDebugEnabled()) {
                log.debug("Server is reading encoded JPEG Stream. Wait a second...");
            }
        } finally {
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }
            imageCaptcha.disposeChallenge();
        }
    }

    /**
     * 验证码验证
     *
     * @param validateCode
     * @param session
     * @return
     */
    public boolean validateCaptchaResponse(String validateCode, HttpSession session) {
        boolean flag = true;
        try {
            imageCaptcha = (ImageCaptcha) session.getAttribute(U.SESSION_CAPTCHA);
            if (imageCaptcha == null) {
                return false;
            }
        /*	if (log.isDebugEnabled()) {
				log.debug(validateCode);
			}*/
            validateCode = validateCode.toUpperCase();
            flag = (imageCaptcha.validateResponse(validateCode)).booleanValue();
            session.removeAttribute(U.SESSION_CAPTCHA);
            return flag;
        } catch (Exception ex) {
            ex.printStackTrace();
            return false;
        }
    }

}
